/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */

#ifndef __BOOTLOADER_H
#define __BOOTLOADER_H
#include <stdint.h>
#include <stdbool.h>
#include "AT32Models.h"

#define Version_ID1 0x10
#define Version_ID2 0x1C



/**
 * @brief
 * TOTAL FLASH SIZE: 256Kb
 * [Bloader:0-14Kb][FWINFO:14-16Kb][APP:16-252Kb][CONFIG0:252-254Kb][CONFIG2:254-256Kb]
 */
#define FLASH_SECTOR_COUNT 128
#define FLASH_SectorSize (uint32_t)2048
#define FLASH_Base_Addr (uint32_t)0x08000000
#define FLASH_IAP_Size (uint32_t)0x4000 // 0x08004000~0x0800FFFF
#define FLASH_APP_ADDR (uint32_t)(FLASH_Base_Addr | FLASH_IAP_Size)

#define FLASH_TOTAL_SIZE (FLASH_SECTOR_COUNT * FLASH_SectorSize)
#define FLASH_END_ADDR (FLASH_Base_Addr + FLASH_TOTAL_SIZE)

#define FLASH_APP_END_ADDR (FLASH_END_ADDR - FLASH_SectorSize * 2)
#define FLASH_APP_SIZE (FLASH_TOTAL_SIZE - FLASH_SectorSize * 3 - FLASH_IAP_Size)

#define FLASH_FWINFO_ADDR (FLASH_APP_ADDR - FLASH_SectorSize)
#define FLASH_CONFIG_ADDR0 (FLASH_APP_END_ADDR + FLASH_SectorSize)
#define FLASH_CONFIG_ADDR1 (FLASH_CONFIG_ADDR0 + FLASH_SectorSize)

#define FRAME_DATA_SIZE FLASH_SectorSize
#define FLASH_FW_MAGIC 0x5A1234A5

#define VESION2INT(MAIN, SUB, BUILD, NUM) (uint32_t)(((MAIN) << 24) | ((SUB) << 16) | ((BUILD) << 8) | (NUM))
#define PID2INT(board, core, product, function) (uint32_t)(((board) << 24) | ((core) << 16) | ((product) << 8) | (function))
#define DATE2INT(YEAR, MONTH, DAY) (uint32_t)(((YEAR) << 16) | ((MONTH) << 8) | (DAY))
enum
{
    CMD_SYNC = 0XF4,
    CMD_ACK = 0XAF,
    CMD_NACK = 0XFC,
    CMD_VERSION = 0X01,
    CMD_GETID = 0X02,
    CMD_WRITE = 0X03,
    CMD_READ = 0X04,
    CMD_RESET = 0X05,
    CMD_JUMP = 0X06,
    CMD_ERASE = 0X07,
    CMD_W_FW_INFO = 0X08,
    CMD_R_FW_INFO = 0X09,
    CMD_LOG = 0X0A,
};

typedef union bootloader
{
    struct
    {
        uint32_t infoCrc;//固件信息校验
        uint32_t magic;//固件信息标志，固定为0x5A1234A5，代码里写入
        uint32_t start_addr;//固件起始地址
        uint32_t size;//固件大小
        uint32_t FWcrc;//固件校验
        uint32_t version;//版本号，格式为：主版本号.子版本号.编译号.序号
        uint32_t pid;//产品ID，格式为：主板ID.核心ID.产品ID.功能ID
        uint32_t date;//编译日期
        uint32_t bootTimes;//启动次数
        AT32_MCU_TYPE whoAmI;
        char name[256];//固件名称，代码里写入，后面再改也行
    };
    uint8_t buffer[FLASH_SectorSize];
} firmware_info_t;

struct pack_info
{
    union
    {
        struct
        {
            uint32_t crc;
            uint32_t addr;
            uint32_t cmd1 : 8;
            uint32_t cmd2 : 8;
            uint32_t data_size : 16;
            uint8_t data[FRAME_DATA_SIZE];
        };
        uint8_t buffer[FRAME_DATA_SIZE + 12];
    };
    uint32_t buffer_size;
};
typedef struct bootloader_info
{
    uint32_t version;
    uint32_t currentAddr;
    uint32_t totalSize;
    uint32_t SizeLeft;
    uint32_t timeOut;
    uint32_t dt;
    uint32_t appAddr;
    uint32_t appSize;
    uint32_t fwInfoAddr;
    uint32_t sectorSize : 16;
    uint32_t sectorCount : 16;
    uint16_t (*read)(uint8_t *buf);
    uint16_t (*write)(uint8_t *buf, uint16_t len);
    uint32_t (*millis)(void);
    void (*flashLock)(void);
    void (*flashUnlock)(void);
    void (*flashSectorErase)(uint32_t addr);
    void (*flashRead)(uint32_t addr, uint8_t *buf, uint32_t len);
    void (*flashWrite)(uint32_t addr, uint8_t *buf, uint32_t len);
    void (*jumpToAddr)(uint32_t addr);
    void (*reset)(void);
    struct pack_info pack;
    firmware_info_t fw_info;
    AT32_MCU_TYPE whoAmI;
    bool synecd;
} bl_info_t;

void bl_pack_clear(bl_info_t *bl);
uint8_t bl_pack_recv(bl_info_t *bl);
void bl_pack_send(bl_info_t *bl, uint8_t cmd, uint32_t addr, uint8_t *data, uint16_t data_size);

void bootloader_handle(bl_info_t *bl);
#endif
